#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gmssl/sm2.h>
#include <gmssl/sm3.h>
#include <gmssl/pem.h>
#include <gmssl/error.h>

int main(int argc, char **argv) {
    if (argc != 4) {
        fprintf(stderr, "Usage: %s <public key PEM file> <input file> <signature file>\n", argv[0]);
        return 1;
    }

    const char *pubkey_filename = argv[1];
    const char *input_filename = argv[2];
    const char *signature_filename = argv[3];

    SM2_KEY key;
    FILE *fp;
    SM3_CTX sm3_ctx;
    uint8_t dgst[32]; // SM3摘要结果大小

    // 读取公钥
    if (!(fp = fopen(pubkey_filename, "r"))) {
        perror("Error opening public key file"); // 使用 perror 打印系统错误信息
        return 1;
    }
    if (!sm2_public_key_info_from_pem(&key, fp)) {
        fprintf(stderr, "Error reading public key from PEM file %s\n", pubkey_filename);
        fclose(fp);
        return 1;
    }
    fclose(fp);

    // 读取输入文件并计算哈希
    if (!(fp = fopen(input_filename, "rb"))) {
        perror("Error opening input file"); // 使用 perror 打印系统错误信息
        return 1;
    }
    
    sm3_init(&sm3_ctx);
    unsigned char buf[1024];
    size_t len;
    while ((len = fread(buf, 1, sizeof(buf), fp)) > 0) {
        sm3_update(&sm3_ctx, buf, len);
    }
    if (ferror(fp)) {
        fprintf(stderr, "Error reading input file %s\n", input_filename);
        fclose(fp);
        return 1;
    }
    sm3_finish(&sm3_ctx, dgst);
    fclose(fp);

    // 读取签名
    unsigned char signature[256];
    size_t siglen;
    if (!(fp = fopen(signature_filename, "rb"))) {
        perror("Error opening signature file"); // 使用 perror 打印系统错误信息
        return 1;
    }
    siglen = fread(signature, 1, sizeof(signature), fp);
    if (ferror(fp)) {
        fprintf(stderr, "Error reading signature file %s\n", signature_filename);
        fclose(fp);
        return 1;
    }
    fclose(fp);

    // 确保读取的签名长度有效
    if (siglen == 0) {
        fprintf(stderr, "Signature file %s is empty or could not be read.\n", signature_filename);
        return 1;
    }

    // 验证签名
    int verify_result = sm2_verify(&key, dgst, signature, siglen);
    if (verify_result == 1) {
        printf("Verify success\n");
    } else {
        fprintf(stderr, "Verify fail\n");
        return 1;
    }

    return 0;
}
